package pcloud.client.remoteservice;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;

import pcloud.client.util.FileResourceInfo;
import pcloud.client.util.GlobalConfig;

import com.googlecode.sardine.DavResource;
import com.googlecode.sardine.Sardine;
import com.googlecode.sardine.SardineFactory;

public class WebDAVService implements FileService
{
	private Sardine sardine;
	private String serviceUrl;

	private WebDAVService()
	{
	};

	public static FileService createInstance(String serviceUrl,
			String username, String password)
	{
		WebDAVService service = new WebDAVService();
		service.sardine = SardineFactory.begin(username, password);
		service.serviceUrl = service.validateRootUrl(serviceUrl);
		return service;
	}

	private String validateRootUrl(String url)
	{
		if (url.charAt(url.length() - 1) == '/') {
			return url.substring(0, url.length() - 1);
		}
		return url;
	}

	@Override
	public boolean createFolder(String path) throws IOException
	{
		String url = getFullPath(path);
		if (sardine.exists(url)) {
			return false;
		}
		sardine.createDirectory(url);
		return true;
	}

	private String getFullPath(String pathFromRoot)
	{
		String url = serviceUrl + pathFromRoot;
		return url;
	}

	public boolean deleteFolder(String path) throws IOException
	{
		String url = getFullPath(path);
		if (sardine.exists(url)) {
			sardine.delete(url);
			return true;
		}
		return false;
	}

	@Override
	public boolean uploadFile(FileResourceInfo fileInfo) throws IOException
	{
		File localFile = new File(fileInfo.getFullPath());
		FileInputStream localStream = new FileInputStream(localFile);
		String remotePath = serviceUrl + fileInfo.getRelativePath();
		uploadFile(remotePath, localStream);
		return true;
	}

	@Override
	public boolean uploadFile(String path, InputStream dataStream)
			throws IOException
	{
		String url = getFullPath(path);
		sardine.put(url, dataStream);
		return true;
	}

	@Override
	public boolean downloadFile(FileResourceInfo fileInfo) throws IOException
	{
		if (!fileInfo.isRemote()) {
			return false;
		}
		String remotePath = fileInfo.getFullPath();
		InputStream remoteStream = downloadFile(remotePath);

		String remoteRootPath = fileInfo.getRootPath();
		String localRootPath = GlobalConfig.getInstance().getLocalSyncFolder(remoteRootPath);
		File localFile = new File(localRootPath+fileInfo.getRelativePath());

		FileOutputStream localFileStream = new FileOutputStream(localFile);
		int bytesRead;
		byte[] buf = new byte[1 * 1024]; // 1K buffer
		while ((bytesRead = remoteStream.read(buf)) != -1) {
			localFileStream.write(buf, 0, bytesRead);
		}
		localFileStream.flush();
		localFileStream.close();
		remoteStream.close();

		return true;
	}

	public InputStream downloadFile(String path) throws IOException
	{
		return sardine.get(path);
	}

	@Override
	public List<FileResourceInfo> list(String path) throws IOException
	{
		List<DavResource> davResourceList = sardine.list(path, 1);
		List<FileResourceInfo> fileInfoList = new LinkedList<FileResourceInfo>();

		for (DavResource davResource : davResourceList) {
			FileResourceInfo fileInfo = createFileResourceInfo(davResource);
			fileInfoList.add(fileInfo);
		}

		return fileInfoList;
	}

	@Override
	public FileResourceInfo getResource(String path) throws IOException
	{
		List<DavResource> davResourceList = sardine.list(path, 0);
		DavResource davResource = davResourceList.get(0);

		FileResourceInfo fileInfo = createFileResourceInfo(davResource);
		return fileInfo;
	}

	private FileResourceInfo createFileResourceInfo(DavResource davResource)
	{
		FileResourceInfo fileInfo = new FileResourceInfo();
		fileInfo.setLength(davResource.getContentLength());
		fileInfo.setCreationDate(davResource.getCreation().getTime());
		fileInfo.setLastModified(davResource.getModified().getTime());
		fileInfo.setFilename(davResource.getName());
		fileInfo.setFullPath(davResource.getPath());
		return fileInfo;
	}

	@Override
	public boolean deleteFile(String path) throws IOException {
		// TODO Auto-generated method stub
		return false;
	}

}
